/********************************************************************
	Created:	2011/02/22    14:23 
	Filename: 	EntityManager.cpp
	Author:		falconwang
*********************************************************************/

#include "Entity.h"
#include "Component.h"
#include "EntityTemplate.h"
#include "EntityManager.h"

Ent::EntityManager::EntityManager()
{

}

Ent::EntityManager::~EntityManager()
{
	Reset();
}

void Ent::EntityManager::AddComponentPrototype(Component* _prototype)
{
	if (_prototype)
	{
		std::map<std::string, Component*>::iterator p = m_CompPrototype.find(_prototype->GetClassName());
		if (p != m_CompPrototype.end())
		{
			delete p->second;
			p->second = _prototype;
		}
		else
		{
			m_CompPrototype[_prototype->GetClassName()] = _prototype;
		}
	}
}

void Ent::EntityManager::RemoveComponentPrototype(Component* _prototype)
{
	if (_prototype)
	{
		std::map<std::string, Component*>::iterator p = m_CompPrototype.find(_prototype->GetClassName());
		if (p != m_CompPrototype.end())
		{
			delete p->second;
			m_CompPrototype.erase(p);
		}
	}
}

Ent::Component* Ent::EntityManager::CreateComponent(const std::string& _className)
{
	std::map<std::string, Component*>::iterator p = m_CompPrototype.find(_className);
	if (p != m_CompPrototype.end())
	{
		return p->second->Clone();
	}

	return 0;
}

void Ent::EntityManager::RemoveAllComponentPrototypes()
{
	std::map<std::string, Component*>::iterator p = m_CompPrototype.begin();
	while (p != m_CompPrototype.end())
	{
		delete p->second;
		p = m_CompPrototype.erase(p);
	}
}

void Ent::EntityManager::AddEntityTemplate(EntityTemplate* _template)
{
	if (_template)
	{
		std::map<std::string, EntityTemplate*>::iterator p = m_Templates.find(_template->GetName());
		if (p != m_Templates.end())
		{
			delete p->second;
			p->second = _template;
		}
		else
		{
			m_Templates[_template->GetName()] = _template;
		}
	}
}

void Ent::EntityManager::RemoveEntityTemplate(EntityTemplate* _template)
{
	if (_template)
	{
		std::map<std::string, EntityTemplate*>::iterator p = m_Templates.find(_template->GetName());
		if (p != m_Templates.end())
		{
			delete p->second;
			m_Templates.erase(p);
		}
	}
}

Ent::EntityTemplate* Ent::EntityManager::GetEntityTemplate(const std::string& _templateName) const
{
	std::map<std::string, EntityTemplate*>::const_iterator p = m_Templates.find(_templateName);
	if (p != m_Templates.end())
	{
		return p->second;
	}
	else
	{
		return 0;
	}
}

void Ent::EntityManager::RemoveAllEntityTemplate()
{
	std::map<std::string, EntityTemplate*>::iterator p = m_Templates.begin();
	while(p != m_Templates.end())
	{
		delete p->second;
		p = m_Templates.erase(p);
	}
}

void Ent::EntityManager::Initialize()
{
	m_eMinID = 0;
}

void Ent::EntityManager::Reset()
{
	m_eMinID = 0;
	RemoveAllEntity();
}

Ent::EntID Ent::EntityManager::GenerateEntityID()
{
	Entity* temp = GetEntity(++m_eMinID);
	while (temp)
	{
		temp = GetEntity(++m_eMinID);
	}

	return m_eMinID;
}

Ent::Entity* Ent::EntityManager::CreateEntity(EntID _eID, const std::string& _eTemplate /*= ""*/, const std::string& _eName /*= "DefEntity"*/)
{
	EntityTemplate* eTemplate = GetEntityTemplate(_eTemplate);
	if (eTemplate)
	{
		return eTemplate->CreateEntity(_eID, _eName);
	}
	else
	{
		return 0;
	}
}

Ent::Entity* Ent::EntityManager::CreateEntity(const std::string& _eTemplate /*= ""*/, const std::string& _eName /*= "DefEntity"*/)
{
	return CreateEntity(GenerateEntityID(), _eTemplate, _eName);
}

void Ent::EntityManager::RemoveEntity(EntID _eId)
{
	Entity* ent = GetEntity(_eId);
	if (ent)
	{
		ent->SetStatus(ENT_STATUS_DESTROY);
		m_DeadEntities.push_back(_eId);
	}
}

void Ent::EntityManager::RemoveDeadEntities()
{
	std::list<EntID>::iterator p			= m_DeadEntities.begin();
	std::map<EntID, Entity*>::iterator q	= m_Entities.begin();

	while (p != m_DeadEntities.end())
	{
		q = m_Entities.find(*p);
		if (q != m_Entities.end())
		{
			delete q->second;
			m_Entities.erase(q);
		}

		p = m_DeadEntities.erase(p);
	}
}

Ent::Entity* Ent::EntityManager::GetEntity(EntID _eId)
{
	std::map<EntID, Entity*>::iterator p	= m_Entities.find(_eId);
	if (p != m_Entities.end())
	{
		return p->second;
	}
	else
	{
		return 0;
	}
}

void Ent::EntityManager::Update(float delta)
{
	if (m_DeadEntities.size() > DEAD_ENTITY_MAX_NUM)
	{
		RemoveDeadEntities();
	}
}

void Ent::EntityManager::RemoveAllEntity()
{
	std::map<EntID, Entity*>::iterator p;
	for (p = m_Entities.begin(); p != m_Entities.end(); p++)
	{
		RemoveEntity(p->first);
	}

	RemoveDeadEntities();
}
